package com.mall.user.services;


import com.alibaba.fastjson.JSON;
import com.mall.commons.tool.exception.ValidateException;
import com.mall.user.IUserService;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.dal.dao.UserMapper;
import com.mall.user.dal.entitys.Member;
import com.mall.user.dal.entitys.User;
import com.mall.user.dal.entitys.UserVerify;
import com.mall.user.dal.persistence.MemberMapper;
import com.mall.user.dal.persistence.UserVerifyMapper;
import com.mall.user.dto.*;
import com.mall.user.utils.AESUtil;
import com.mall.user.utils.ExceptionProcessorUtils;
import com.mall.user.utils.JwtTokenUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * @author looper
 * @
 **/
@Service
@Log4j2
@Component
public class UserServiceImpl implements IUserService {


    public static String USER_INFO_KEY = "userInfo";

    @Autowired
    UserMapper mapper;

    @Autowired
    MemberMapper memberMapper;

    @Autowired
    UserVerifyMapper userVerifyMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Override
    public UserLoginResponse userLogin(UserLoginRequest request) {

        request.requestCheck();

        UserLoginResponse userLoginResponse = new UserLoginResponse();

        //密码加密
        String PWD = new AESUtil(request.getPassword()).encrypt();
        User userSelect = new User();
        userSelect.setUsername(request.getUserName());
        userSelect.setPassword(PWD);
        Example example = new Example(Member.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", userSelect.getUsername());
        criteria.andEqualTo("password", userSelect.getPassword());
        List<Member> members = memberMapper.selectByExample(example);
        //size不为0那么登录成功
        if (members.size() != 0) {
            log.info("用户登入成功,登入用户:{}", JSON.toJSONString(request));
            Member member = members.get(0);
            //看是否激活
            if ("N".equals(member.getIsVerified())) {
                Example exampleVerify = new Example(UserVerify.class);
                exampleVerify.createCriteria().andEqualTo("username", member.getUsername());
                List<UserVerify> userVerifies = userVerifyMapper.selectByExample(exampleVerify);
                //开一个线程单独发邮件
                Thread thread = new Thread(() -> {
                    log.info("发送邮件");
                    senderEmail(member, userVerifies.get(0));
                });
                thread.start();
                //未激活不允许登入
                userLoginResponse.setCode(SysRetCodeConstants.USER_ISVERFIED_ERROR.getCode());
                userLoginResponse.setMsg(SysRetCodeConstants.USER_ISVERFIED_ERROR.getMessage());
                return userLoginResponse;
            }
            BeanUtils.copyProperties(member, userLoginResponse);
            userLoginResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
            userLoginResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
            HashMap<String, Object> map = new HashMap<>();
            map.put("uid", member.getId());
            map.put("username", member.getUsername());
            //token
            userLoginResponse.setToken(JwtTokenUtils.builder().msg(JSON.toJSONString(map)).build().creatJwtToken());
        } else {
            userLoginResponse.setCode(SysRetCodeConstants.USERORPASSWORD_ERRROR.getCode());
            userLoginResponse.setMsg(SysRetCodeConstants.USERORPASSWORD_ERRROR.getMessage());
        }

        return userLoginResponse;
    }

    /**
     * 注册
     *
     * @param request
     * @return
     */
    @Override
    public UserRegisterResponse userRegister(UserRegisterRequest request) {
        UserRegisterResponse response = new UserRegisterResponse();
        request.requestCheck();
        volidUserNameRepeat(request);
        Member member = new Member();
        member.setUsername(request.getUserName());

        String encryptPWD = new AESUtil(request.getUserPwd()).encrypt();

        //验证邮箱或者帐号是否重复
        Boolean isEXISTS = isAlreadEXISTS(request);
        if (isEXISTS){
            response.setCode(SysRetCodeConstants.USERNAME_OR_EMAIL_ALREADY_EXISTS.getCode());
            response.setMsg(SysRetCodeConstants.USERNAME_OR_EMAIL_ALREADY_EXISTS.getMessage());
            return response;
        }


        member.setPassword(encryptPWD);
        member.setEmail(request.getEmail());
        member.setCreated(new Date());
        member.setUpdated(new Date());
        member.setIsVerified("N");
        member.setState(1);



        Integer code = 0;
        try {
            code = memberMapper.insert(member);
        } catch (Exception e) {
            e.printStackTrace();
         ExceptionProcessorUtils.wrapperHandlerException(response,e);
            return response;
        }
        if (code != 1) {
            response.setCode(SysRetCodeConstants.USER_REGISTER_FAILED.getCode());
            response.setMsg(SysRetCodeConstants.USER_REGISTER_FAILED.getMessage());
            return response;
        }
        UserVerify userVerify = new UserVerify();
        userVerify.setUsername(member.getUsername());
        //姓名加加密后的密码加上6位UUID
        userVerify.setUuid(member.getUsername() + encryptPWD + UUID.randomUUID().toString().substring(0, 6));
        userVerify.setRegisterDate(new Date());
        userVerify.setIsExpire("N");
        userVerify.setIsVerify("N ");
        Integer codeVerify = userVerifyMapper.insert(userVerify);
        if (codeVerify != 1) {
            response.setCode(SysRetCodeConstants.USERVERIFY_INFOR_INVALID.getCode());
            response.setMsg(SysRetCodeConstants.USERVERIFY_INFOR_INVALID.getMessage());
            return response;
        }

        //邮件
        Thread thread = new Thread(() -> senderEmail(member, userVerify));
        thread.start();

        log.info("注册成功:{}", JSON.toJSONString(request));
        response.setCode(SysRetCodeConstants.SUCCESS.getCode());
        response.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return response;

    }

    private Boolean isAlreadEXISTS(UserRegisterRequest request) {
        Example exampleName = new Example(Member.class);
        exampleName.createCriteria().andEqualTo("username",request.getUserName());
        List<Member> nameList = memberMapper.selectByExample(exampleName);

        Example exampleEmail = new Example(Member.class);
        exampleEmail.createCriteria().andEqualTo("email",request.getEmail());
        List<Member> emailList = memberMapper.selectByExample(exampleEmail);

        if (nameList.size()!=0||emailList.size()!=0){
            return true;

        }
        return false;

    }

    @Transactional
    @Override
    public UserVerifyResponse getVerify(UserVerifyRequest userVerifyRequest) {
        UserVerifyResponse userVerifyResponse = new UserVerifyResponse();
        String uuid = userVerifyRequest.getUuid();
        Example example = new Example(UserVerify.class);
        example.createCriteria().andEqualTo("uuid", uuid);
        List<UserVerify> userVerifies = userVerifyMapper.selectByExample(example);
        if (userVerifies.size() == 0) {
            //没查到,数据库异常了
            userVerifyResponse.setMsg(SysRetCodeConstants.DB_EXCEPTION.getMessage());
            userVerifyResponse.setCode(SysRetCodeConstants.DB_EXCEPTION.getCode());
        }
        //1.根据uuid从激活表拿到用户名字
        UserVerify userVerify = userVerifies.get(0);
        //2.修改两个表激活和member表的激活状态
        Example updateExample = new Example(UserVerify.class);
        updateExample.createCriteria().andEqualTo("username", userVerify.getUsername());
        userVerify.setIsVerify("Y");
        Integer code = userVerifyMapper.updateByExampleSelective(userVerify, updateExample);
        if (code == 0) {
            userVerifyResponse.setMsg(SysRetCodeConstants.DB_EXCEPTION.getMessage());
            userVerifyResponse.setCode(SysRetCodeConstants.DB_EXCEPTION.getCode());
        }
        Example memberExample = new Example(Member.class);
        memberExample.createCriteria().andEqualTo("username", userVerify.getUsername());
        Member member = new Member();
        member.setIsVerified("Y");
        member.setUsername(userVerify.getUsername());
        Integer codeMember = null;
        try {
            codeMember = memberMapper.updateByExampleSelective(member, memberExample);
        } catch (Exception e) {
            e.printStackTrace();
            ExceptionProcessorUtils.wrapperHandlerException(userVerifyResponse, e);
        }
        if (codeMember == 0) {
            userVerifyResponse.setMsg(SysRetCodeConstants.DB_EXCEPTION.getMessage());
            userVerifyResponse.setCode(SysRetCodeConstants.DB_EXCEPTION.getCode());
        }
        userVerifyResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        userVerifyResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        return userVerifyResponse;
    }



    /**
     * 拦截器验证token
     * @param checkAuthRequest
     * @return
     */
    @Override
    public CheckAuthResponse validToken(CheckAuthRequest checkAuthRequest) {
        CheckAuthResponse checkAuthResponse = new CheckAuthResponse();

        //调用一个方法来验证这个状态有没有对应的token ,加密的时候是放入uid和username的map,解密使用freejwt方法,会返回解密的内容
        String token = checkAuthRequest.getToken();
        if (StringUtils.isEmpty(token)){
            checkAuthResponse.setCode(SysRetCodeConstants.REQUEST_DATA_NOT_EXIST.getCode());
            checkAuthResponse.setMsg(SysRetCodeConstants.REQUEST_DATA_NOT_EXIST.getMessage());
            return checkAuthResponse;
        }
        //非空  解密
        String userinfo = JwtTokenUtils.builder().token(token).build().freeJwt();
        //如果解密没有报错说明解密成功 这里的userinfo是map类型的json字符串!!
        // TODO: 2021/12/13 从token解析出的信息是map类型json字符串的信息
        log.info("解密的用户信息是:{}", JSON.toJSONString(userinfo));
        //userinfo  -> uid # username
        checkAuthResponse.setUserinfo(userinfo);
        //code 和 msg
        checkAuthResponse.setCode(SysRetCodeConstants.SUCCESS.getCode());
        checkAuthResponse.setMsg(SysRetCodeConstants.SUCCESS.getMessage());
        return checkAuthResponse;
    }

    @Override
    public UserLoginResponse getUserById(Long userId) {
        UserLoginResponse userLoginResponse = new UserLoginResponse();
        Member member = memberMapper.selectByPrimaryKey(userId);
        BeanUtils.copyProperties(member,userLoginResponse);
        return userLoginResponse;


    }

    private void senderEmail(Member member, UserVerify userVerify) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("mycskaoyan2021@163.com");
        message.setTo(member.getEmail());
        message.setSubject("csmall商城激活");
        message.setText("http://127.0.0.1:8080/user/verify?uuid=" + userVerify.getUuid());
        javaMailSender.send(message);
    }

    private void volidUserNameRepeat(UserRegisterRequest request) {
        Example example = new Example(Member.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", request.getUserName());
        List<User> users = mapper.selectByExample(example);
        if (users.size() != 0) {
            throw new ValidateException(SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getCode(),
                    SysRetCodeConstants.USERNAME_ALREADY_EXISTS.getMessage());
        }


    }
}
